package com.slink.xin.framework.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 日期处理类
 *
 * 包括对日期格式化和日期的操作
 * 
 * @author 新
 */
public class DateUtils {

	// s转换为 xx:xx:xx
	public static String secToTime(int time) {
		String timeStr = null;
		int hour = 0;
		int minute = 0;
		int second = 0;
		if (time <= 0)
			return "00:00:00";
		else {
			minute = time / 60;
			if (minute < 60) {
				second = time % 60;
				timeStr = "00:" + unitFormat(minute) + ":" + unitFormat(second);
			} else {
				hour = minute / 60;
				if (hour > 99)
					return "99:59:59";
				minute = minute % 60;
				second = time - hour * 3600 - minute * 60;
				timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":"
						+ unitFormat(second);
			}
		}
		return timeStr;
	}

	public static String unitFormat(int i) {
		String retStr = null;
		if (i >= 0 && i < 10)
			retStr = "0" + Integer.toString(i);
		else
			retStr = "" + i;
		return retStr;
	}

	/**
	 * 这个是在java里的日期格式
	 */
	public static String format = "yyyy-MM-dd HH:mm:ss";
	public static String format1 = "yyyy-MM-dd";

	/**
	 * 这个是在oracle里的日期格式
	 */
	public static String format2 = "yyyy-MM-dd HH24:mi:ss";
	public static String format3 = "yyyy-MM-dd HH24:mi:ss.S";

	private final static String[] chineseWeekNames = { "星期日", "星期一", "星期二",
			"星期三", "星期四", "星期五", "星期六" };

	/**
	 * 根据给定的日期串 转化成日期
	 */
	public static Date getMaxDateCentury() {
		try {
			SimpleDateFormat formatter = new SimpleDateFormat(format1);
			Date ret = formatter.parse("3000-00-00");
			return ret;
		} catch (Exception ex) {
			return new Date();
		}
	}

	/**
	 * 根据给定的日期串 转化成日期
	 */
	public static Date parseDate(String date, String format) {
		try {
			SimpleDateFormat formatter = new SimpleDateFormat(format);
			Date ret = formatter.parse(date);
			return ret;
		} catch (Exception ex) {
			return new Date();
		}
	}

	/**
	 * 根据给定的年、月、日 转化成日期
	 */
	public static Date parseDate(int y, int m, int d) {
		// Calendar的月份从0~11,0是1月份，1是二月份，依次类推
		Calendar ca = Calendar.getInstance();
		ca.set(y, m - 1, d, 0, 0);
		return ca.getTime();
	}

	/**
	 * 将指定日期格式化为指定格式字符串，格式可以自己定义，也可以采用 format 和 format1
	 *
	 * 如果格式有问题，返回空字符串
	 */
	public static String formatDate(Date date, String format) {
		if (date == null)
			return "";
		try {
			SimpleDateFormat formatter = new SimpleDateFormat(format,
					java.util.Locale.US);
			String ret = formatter.format(date);
			return ret;
		} catch (Exception e) {
			return "";
		}
	}

	/**
	 * 返回格式化的日期串
	 */
	public static String formatDate(Date date) {
		return formatDate(date, format1);
	}

	/**
	 * 返回格式化的日期时间串
	 */
	public static String formatDateTime(Date date) {
		return formatDate(date, format);
	}

	/**
	 * 得到今天的日期 没有时间
	 * 
	 * @return
	 */
	public static java.util.Date getToday() {
		Calendar ca = Calendar.getInstance();
		ca.setTime(new Date());
		ca.set(Calendar.HOUR_OF_DAY, 0);
		ca.set(Calendar.SECOND, 0);
		ca.set(Calendar.MINUTE, 0);
		ca.set(Calendar.MILLISECOND, 0);
		return ca.getTime();
	}

	/**
	 * 得到明天,今天日期加1，含时间
	 * 
	 * @return
	 */
	public static java.util.Date getTomorrow() {
		return addDay(new java.util.Date(), 1);
	}

	/**
	 * 得到昨天,今天日期减1，含时间
	 * 
	 * @return
	 */
	public static java.util.Date getYesterday() {
		return addDay(new java.util.Date(), -1);
	}

	/**
	 * 得到指定日期所在月的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static java.util.Date getMinDay(Date date) {
		return setDay(date, 1);
	}

	/**
	 * 取某月的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static java.util.Date getMaxDay(Date date) {
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		return setDay(date, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
	}

	/**
	 * 返回某年某月有多少天
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static int getDaysOfMonth(int year, int month) {
		Calendar calendar = new GregorianCalendar();
		calendar.set(year, month - 1, 1);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 得到日期的年份
	 * 
	 * @param date
	 * @return
	 */
	public static int getYear(java.util.Date date) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 得到日期的年份
	 * 
	 * @param date
	 * @return
	 */
	public static int getYearTimeByZoneId(java.util.Date date, String timeZoneId) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm",
				Locale.US);
		// 时区
		if (StringUtil.isNotBlank(timeZoneId)) {
			format.setTimeZone(TimeZone.getTimeZone(timeZoneId));// 设置时区
		} else {
			format.setTimeZone(TimeZone.getDefault());
		}
		Calendar calendar = format.getCalendar();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 得到日期的月份
	 * 
	 * @param date
	 * @return
	 */
	public static int getMonth(java.util.Date date) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH) + 1;
	}

	/**
	 * 得到日期的天(月中)
	 * 
	 * @param date
	 * @return
	 */
	public static int getDay(java.util.Date date) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 得到年，月，日的数组
	 * 
	 * @param date
	 * @return
	 */
	public static int[] getYMD(java.util.Date date) {
		int[] ymd = new int[3];
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		ymd[0] = calendar.get(Calendar.YEAR);
		ymd[1] = calendar.get(Calendar.MONTH) + 1;
		ymd[2] = calendar.get(Calendar.DAY_OF_MONTH);
		return ymd;
	}

	/**
	 * 返回 星期
	 * 
	 * @param number
	 * @return
	 */
	public static String getChineseWeek(int number) {
		if (number < 0 || number > 6) {
			return null;
		}
		return chineseWeekNames[number];
	}

	// 转化为java.sql.Date
	public static java.sql.Date getSqlDate(Date date) {
		return new java.sql.Date(date.getTime());
	}

	// 转化为java.util.Date
	public static java.util.Date getDate(java.sql.Date date) {
		return new java.sql.Date(date.getTime());
	}

	/**
	 * 比较两个时间的大小
	 * 
	 * @return 0 : 相等 1:大于 -1：小于
	 * 
	 *         注意：这里传入的月份是真实月份，不需要减1
	 */
	public static int CompareTime(int y1, int m1, int d1, int y2, int m2, int d2) {
		int longtime1, longtime2;
		Calendar ca = Calendar.getInstance();
		ca.set(y1, m1 - 1, d1);
		longtime1 = ca.get(Calendar.DAY_OF_YEAR);
		ca.set(y2, m2 - 1, d2);
		longtime2 = ca.get(Calendar.DAY_OF_YEAR);
		if (y1 > y2)
			return 1;
		if (y1 < y2)
			return -1;
		else {
			if (longtime1 > longtime2)
				return 1;
			else if (longtime1 < longtime2)
				return -1;
			else
				return 0;
		}
	}

	/**
	 * 比较当前日期跟指定日期的大小
	 * 
	 * @param y2
	 *            年
	 * @param m2
	 *            月
	 * @param d2
	 *            日
	 * @return
	 */
	public static int CompareTime(int y2, int m2, int d2) {
		Calendar ca = Calendar.getInstance();
		ca.setTime(new Date());
		return CompareTime(ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1,
				ca.get(Calendar.DATE), y2, m2, d2);
	}

	/**
	 * 比较当前日期跟指定日期的大小
	 * 
	 * @param date
	 * @return
	 */
	public static int CompareTime(Date date) {
		Calendar ca1 = Calendar.getInstance();
		ca1.setTime(new Date());
		Calendar ca2 = Calendar.getInstance();
		ca2.setTime(date);
		return CompareTime(ca1.get(Calendar.YEAR), ca1.get(Calendar.MONTH) + 1,
				ca1.get(Calendar.DATE), ca2.get(Calendar.YEAR),
				ca2.get(Calendar.MONTH) + 1, ca2.get(Calendar.DATE));
	}

	/**
	 * 比较当前日期跟指定日期的大小(精确到s) -1:ca1 < ca2 0:相等 1: ca1 > ca2
	 * 
	 * @param date
	 * @return
	 */
	public static int CompareTimeInSeconds(Date date) {
		Calendar ca1 = Calendar.getInstance();
		ca1.setTime(new Date());
		Calendar ca2 = Calendar.getInstance();
		ca2.setTime(date);
		return ca1.compareTo(ca2);
	}

	/**
	 * 比较两个指定日期的大小
	 * 
	 * @param date1
	 *            date2
	 * @return
	 */
	public static int CompareTime(Date date1, Date date2) {
		Calendar ca1 = Calendar.getInstance();
		ca1.setTime(date1);
		Calendar ca2 = Calendar.getInstance();
		ca2.setTime(date2);
		return CompareTime(ca1.get(Calendar.YEAR), ca1.get(Calendar.MONTH) + 1,
				ca1.get(Calendar.DATE), ca2.get(Calendar.YEAR),
				ca2.get(Calendar.MONTH) + 1, ca2.get(Calendar.DATE));
	}

	/**
	 * 判断某个时间是否属于一个时间段内 (y2的时间大于y1 的时间)
	 * 
	 * @param y
	 * @param m
	 * @param d
	 * @param y1
	 *            开始日期 年
	 * @param m1
	 *            开始日期 月
	 * @param d1
	 *            开始日期 日
	 * @param y2
	 *            结束日期 年
	 * @param m2
	 *            结束日期 月
	 * @param d2
	 *            结束日期 日
	 * @return
	 */
	public static boolean hasInDate(int y, int m, int d, int y1, int m1,
			int d1, int y2, int m2, int d2) {
		int longtime1, longtime2, longtime;
		Calendar ca = Calendar.getInstance();
		ca.set(y, m, d);
		longtime = ca.get(Calendar.DAY_OF_YEAR);
		ca.set(y1, m1, d1);
		longtime1 = ca.get(Calendar.DAY_OF_YEAR);
		ca.set(y2, m2, d2);
		longtime2 = ca.get(Calendar.DAY_OF_YEAR);
		if ((y > y1) && (y < y2))
			return true;
		else if ((y == y2) && (longtime <= longtime2))
			return true;
		else if ((y == y1) && (longtime >= longtime1))
			return true;
		else
			return false;
	}

	/**
	 * 取两个日期相减得到的月数 如 2007-04-24 和 2007-11-13 相差 6 个月
	 * 
	 * @param start
	 * @param end
	 * @return
	 */
	public static int durnMonths(Date start, Date end) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(start);
		int startDate = calendar.get(Calendar.DATE);
		int startMonth = calendar.get(Calendar.MONTH);
		int startYear = calendar.get(Calendar.YEAR);
		calendar.setTime(end);
		int endDate = calendar.get(Calendar.DATE);
		int endMonth = calendar.get(Calendar.MONTH);
		int endYear = calendar.get(Calendar.YEAR);
		int number = 1;
		// 年相减 X 12 + 月相减

		number = (endYear - startYear) * 12;
		number += (endMonth - startMonth);

		// 日期相减，< 0 说明不够一月，月减1
		if (endDate - startDate < 0)
			number--;
		return number;
	}

	/**
	 * 计算两个时间之间的天数差异（不足n*24小时的视为n-1天）
	 *
	 * 注意！！！！！！ start是结束时间
	 *
	 * @param start
	 * @param end
	 * @return
	 */
	public static int durnDays(Date start, Date end) {
		return (int) ((end.getTime() - start.getTime()) / (86400 * 1000));
	}

	/**
	 * 根据字符串得到日期
	 * 
	 * @param date
	 * @return
	 */
	public static Date str2Date(String date) {
		if (date.length() > 10)
			return parseDate(date, format);
		else
			return parseDate(date, format1);
	}

	/**
	 * 根据字符串得到指定格式的日期
	 * 
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static Date str2Date(String date, String pattern) {
		return parseDate(date, pattern);
	}

	/**
	 * 将日期的年份加减 只有日期 没有时间
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addYear(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, amount);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DATE), 0, 0, 0);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 将日期的月份加减 只有日期 没有时间
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addMonth(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, amount);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DATE), 0, 0, 0);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 将日期的天数加减 只有日期 没有时间
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addDay(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		if (date == null)
			date = new Date();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, amount);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DATE), 0, 0, 0);
		return calendar.getTime();
	}

	/**
	 * 将日期的月份加减
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addMonthWithTime(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, amount);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 将日期的天数加减
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addDayWithTime(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, amount);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 将日期的天数加减
	 * 
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addSecondWithTime(java.util.Date date, int amount) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.SECOND, amount);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 设置特定的月 包含具体时间
	 * 
	 * @param date
	 * @param month
	 * @return
	 */
	public static Date setMonth(java.util.Date date, int month) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.set(Calendar.MONTH, month - 1);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 设置特定的天(月中)
	 * 
	 * @param date
	 * @param day
	 * @return
	 */
	public static Date setDay(java.util.Date date, int day) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, day);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 获取某年第一天日期
	 * 
	 * @param year
	 *            年份
	 * @return Long
	 */
	public static Long getCurrYearFirst(int year, Calendar calendar) {
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		Date currYearFirst = calendar.getTime();
		return currYearFirst.getTime();
	}

	/**
	 * 获取某年最后一天日期
	 * 
	 * @param year
	 *            年份
	 * @return Long
	 */
	public static Long getCurrYearLast(int year, Calendar calendar) {
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.roll(Calendar.DAY_OF_YEAR, -1);
		Date currYearLast = calendar.getTime();

		return currYearLast.getTime();
	}

	/**
	 * 获取某年第一天日期
	 * 
	 * @param year
	 *            年份
	 * @return Long
	 */
	public static Long getCurrYearFirst(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		Date currYearFirst = calendar.getTime();
		return currYearFirst.getTime();
	}

	/**
	 * 获取某年最后一天日期
	 * 
	 * @param year
	 *            年份
	 * @return Long
	 */
	public static Long getCurrYearLast(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year + 1);
		// 回退一秒
		calendar.roll(Calendar.SECOND, -1);
		Date currYearLast = calendar.getTime();
		// 减去一秒
		return currYearLast.getTime() - 119000L;
	}

	/**
	 * 检查字符串日期是否合法
	 * 
	 * @param dateStr
	 * @return
	 */
	public static boolean checkDate(String dateStr) {
		try {
			String[] dateStrs = dateStr.split("-");
			if (null == dateStrs || dateStrs.length != 3) {
				return false;
			}
			int year = Integer.parseInt(dateStrs[0]);
			int month = Integer.parseInt(dateStrs[1]);
			int day = Integer.parseInt(dateStrs[2]);

			if (month < 1 || month > 12) {
				return false;
			}
			int maxday = getDaysOfMonth(year, month);
			if (day < 1 || day > maxday) {
				return false;
			}

			if (year < 1000 || year > 9999)
				return false;
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static int getFullDateWeekTime(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0)
			w = 0;
		return w;
	}

	/**
	 * 特殊的时间处理，计算前两个月的日期,用于客户信息投放，xiongrui@sogou-inc.com,20110429
	 * eg:2011-5-1->2011-3-1 eg:2011-4-14->2011-2-14 eg:2011-4-30->2011-3-1
	 * eg:2011-4-29->2011-3-1 eg:2011-4-28->2011-2-28
	 */
	public static String beforeTwoMonth(Date date) {

		int yearInt = DateUtils.getYear(date);
		int monthInt = DateUtils.getMonth(date);
		int dateInt = DateUtils.getDay(date);

		if (monthInt <= 2) {
			yearInt = yearInt - 1;
			monthInt += 10;
		} else {
			monthInt -= 2;
		}

		String monthStr = monthInt < 10 ? "0" + monthInt : "" + monthInt;
		String dateStr = dateInt < 10 ? "0" + dateInt : "" + dateInt;
		String beforeDate = "" + yearInt + "-" + monthStr + "-" + dateStr;

		if (DateUtils.checkDate(beforeDate)) {
			return beforeDate;
		} else {
			monthStr = (monthInt + 1) < 10 ? "0" + (monthInt + 1) : ""
					+ (monthInt + 1);
			return "" + yearInt + "-" + monthStr + "-01";
		}
	}

	/**
	 *
	 * @param table
	 *            数据库表
	 * @param date
	 *            要指定的查询日期
	 * @param startDate
	 *            (include)包含开始时间
	 * @param endDate
	 *            (exclude)不包含结束时间
	 * @param order
	 *            顺序 null,desc,asc,
	 * @return
	 */
	public static String getDateRangeSqlLeftClose(String table, String date,
			Date startDate, Date endDate, String order) {
		String statdate = DateUtils.formatDate(startDate);
		String enddate = DateUtils.formatDate(endDate);
		String orderSql = " ";
		if (order != null) {
			orderSql = " order by " + date + " " + order;
		}
		String sql = "select * from " + table + " where to_char(" + date
				+ " , 'yyyy-MM-dd')" + " >= " + "'" + statdate + "'"
				+ " and to_char(" + date + " , 'yyyy-MM-dd')" + " < " + "'"
				+ enddate + "'" + orderSql;
		return sql;
	}

	/**
	 *
	 * @param table
	 *            数据库表
	 * @param date
	 *            要指定的查询日期
	 * @param startDate
	 *            (include)包含开始时间
	 * @param endDate
	 *            (include)包含结束时间
	 * @param order
	 *            顺序 null,desc,asc,
	 * @return
	 */
	public static String getDateRangeSqlFullClose(String table, String date,
			Date startDate, Date endDate, String order) {
		String statdate = DateUtils.formatDate(startDate);
		String enddate = DateUtils.formatDate(endDate);
		String orderSql = " ";
		if (order != null) {
			orderSql = " order by " + date + " " + order;
		}
		String sql = "select * from " + table + " where to_char(" + date
				+ " , 'yyyy-MM-dd')" + " >= " + "'" + statdate + "'"
				+ " and to_char(" + date + " , 'yyyy-MM-dd')" + " <= " + "'"
				+ enddate + "'" + orderSql;
		return sql;
	}

	/**
	 * 根据用户生日计算年龄
	 */
	public static int getAgeByBirthday(Date birthday) {
		if (birthday == null)
			return 0;

		Calendar cal = Calendar.getInstance();

		if (cal.before(birthday)) {
			throw new IllegalArgumentException(
					"The birthDay is before Now.It's unbelievable!");
		}

		int yearNow = cal.get(Calendar.YEAR);
		int monthNow = cal.get(Calendar.MONTH) + 1;
		int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

		cal.setTime(birthday);
		int yearBirth = cal.get(Calendar.YEAR);
		int monthBirth = cal.get(Calendar.MONTH) + 1;
		int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

		int age = yearNow - yearBirth;

		if (monthNow <= monthBirth) {
			if (monthNow == monthBirth) {
				if (dayOfMonthNow < dayOfMonthBirth) {
					age--;
				}
			} else {
				age--;
			}
		}
		return age;
	}

	/**
	 * 根据年龄计算出生年份
	 */
	public static Integer getBirthYearByAge(Integer age) {
		Calendar mycalendar = Calendar.getInstance();
		int year = mycalendar.get(Calendar.YEAR);
		int birthYear = year - age;
		return birthYear;
	}
}
